#pragma once
#include "../logger.hpp"
#include "message.hxx"
#include "message-odb.hxx"
#include <algorithm>
#include <bits/stdint-uintn.h>
#include <boost/date_time/posix_time/ptime.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
#include <cstdlib> 
#include <iostream>
#include <memory>
#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <sstream>
#include <string>
#include <fmt/core.h>
#include <boost/date_time/posix_time/posix_time.hpp>

namespace shared {

namespace dal {

class MessageDao;
using MessageDaoPtr = std::shared_ptr<MessageDao>;

class MessageDao
{
    using query = odb::query<entity::Message>;
    using result = odb::result<entity::Message>;
    using QueryMaker = std::function<result()>;
    using MessageList = std::vector<entity::Message>;
public:
    MessageDao(const std::shared_ptr<odb::mysql::database>& db) : db_(db) {}
    // 新增一条消息数据
    bool insert(entity::Message& message)
    {
        try {
            odb::transaction trans(db_->begin());
            db_->persist(message);
            trans.commit();
        } catch (const std::exception& e) {
            LOG_ERROR("新增消息({})失败: {}", message.messageId(), e.what());
            return false;
        }
        return true;
    }
    // 删除指定会话的所有消息
    bool remove(const std::string& sessionId)
    {
        try {
            odb::transaction trans(db_->begin());
            db_->erase_query<entity::Message>(query::sessionId == sessionId);
            trans.commit();
        } catch (const std::exception& e) {
            LOG_ERROR("删除会话({})消息失败: {}", sessionId, e.what());
            return false;
        }
        return true;
    }
    MessageList selectRecentMessages(const std::string& sessionId, uint32_t count) 
    {
        std::string errlogInfo = fmt::format("查询会话({})中最近{}条消息失败", sessionId, count);
        std::string queryString = fmt::format(
            "session_id='{}' order by create_time desc limit {}",
            sessionId, count
        ); 
        return selectMessage(errlogInfo, [&](){
            return db_->query<entity::Message>(queryString);
        });
    }
    MessageList selectRangeMessages(const std::string& sessionId,
        const boost::posix_time::ptime& begin, const boost::posix_time::ptime& end) 
    {
        std::string errlogInfo = fmt::format(
            "查询会话({})中{}-{}的区间消息失败", 
            sessionId,
            boost::posix_time::to_simple_string(begin),
            boost::posix_time::to_simple_string(end)
        );
        return selectMessage(errlogInfo, [&](){
            return db_->query<entity::Message>(
                query::sessionId == sessionId && 
                query::createTime >= begin &&
                query::createTime <= end
            );
        });
    }
private:
    MessageList selectMessage(const std::string& log, const QueryMaker& queryCond) 
    {
        MessageList selectMessages;   
        try {
            odb::transaction trans(db_->begin());
            typedef odb::result<entity::Message> result;
            result ret(queryCond());
            for(auto it = ret.begin(); it != ret.end(); ++it) {
                selectMessages.emplace_back(*it);
            }
            trans.commit();
        } catch (const std::exception& e) {
            LOG_ERROR("{}: {}", log, e.what());
        }
        return selectMessages;
    }
private:
    std::shared_ptr<odb::mysql::database> db_;
};


}}